#ifndef VIDEOPLAYER_H
#define VIDEOPLAYER_H

#include <QObject>
#include "sdlcondmutex.h"
extern "C"{
    #include <libavutil/avutil.h>
    #include <libswresample/swresample.h>
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libswscale/swscale.h>
}

class VideoPlayer : public QObject
{
    Q_OBJECT
public:
    typedef enum{//播放状态
        Stopped = 0,
        Playing,
        Paused
    }State;

    typedef enum{
        Min = 0,
        Max = 100
    }Volume;

    typedef struct{
        int width;
        int height;
        AVPixelFormat pixFmt;
        int size;
    }VideoSwsSpec;//画面参数

    typedef struct{
        int     nSampleRate;//采样率
        AVSampleFormat  sampleFmt;//采样深度 8位,16位,32位
        int     nChLayout;//声道布局
        int     nCh;//声道数
        int     bytesPerSampleFrame;//??
    }AudioSwrSpec;
public:
    explicit VideoPlayer(QObject *parent = nullptr);
    ~VideoPlayer();
    void play();
    void pause();
    void stop();
    void setState(State state);
    bool isPlaying();
    //获取当前的状态
    State getState();
    void setFileName(const QString& fileName);
    QString getFileName();
    //获取总时长(单位是妙，1秒=1000毫秒=1000000微妙)
    int getDuration();
    // 当前的播放时刻（单位是秒)
    int getTime();
    // 设置当前的播放时刻（单位是秒）
    void setTime(int seekTime);
    //设置音量
    void setVolumn(int volume);
    //获取音量
    int getVolumn();
    //设置静音
    void setMute(bool mute);
    bool isMute();

signals:
    void playFailed(VideoPlayer *player);
    void stateChanged(VideoPlayer* player);
    void initFinished(VideoPlayer* player);
    void timeChanged(VideoPlayer* player);
    void frameDecoded(VideoPlayer* player,uint8_t * data,VideoSwsSpec& swsOutSpec);
public slots:
    void onVolumeChanged(int value);
    void onSpeedPlay(double rate);
private:
     //音频相关
     //解码上下文
     AVCodecContext* m_aDecodeCtx = nullptr;
     //音频流
     AVStream* m_aStream = nullptr;
     //存放音频包的列表
     std::list<AVPacket> m_aPktList;
     //音频包列表的锁
     SDLCondMutex m_aMutex;
     //音频重采样上下文
     SwrContext* m_aSwrCtx = nullptr;
    //音频重采样输入输出参数
     AudioSwrSpec m_aSwrInSpec;
     AudioSwrSpec m_aSwrOutSpec;
    //音频重采样输入输出frame
     AVFrame*     m_aSwrInFrame = nullptr;
     AVFrame*     m_aSwrOutFrame = nullptr;

     //音频重采样输出PCM的索引
     int          m_aSwrOutIdx = 0;
     //音频重采样输出PCM的大小
     int          m_aSwrOutSize = 0;
     //音频时钟，当前音频包对应的时间值
     double m_aTime;
     int    m_volume;
     bool   m_mute;
     //是否有音频流
     bool       m_bHasAudio = false;
     int            m_aSeekTime = -1;
     //音频资源是否可以释放
     bool         m_aCanFree = false;
     //外面设置的当前播放时刻(用于完成seek功能)

private:
     //视频相关
     //解码上下文
     AVCodecContext* m_vDecodeCtx = nullptr;
     //流
     AVStream*      m_vStream = nullptr;
     //像素格式转换的输入输出frame
     AVFrame*       m_vSwsInFrame = nullptr;
     AVFrame*       m_vSwsOutFrame = nullptr;
     //像素格式转换上下文
     SwsContext*    m_vSwsCtx = nullptr;
     //像素格式转换输出frame的参数
     VideoSwsSpec   m_vSwsOutSpec;
     //视频包列表锁
     SDLCondMutex   m_vMutex;
     //视频时钟
     double         m_vTime = 0;
     //是否有视频流
     bool           m_bHasVideo = false;
     //外面设置的当前播放时刻
     int            m_vSeekTime = -1;
     //音频资源是否可以释放
     bool           m_vCanFree = false;
     std::list<AVPacket> m_vPktList;
public:
     // 初始化SDL
     int initSDL();
     //初始化音频信息
     int initAudioInfo();
     //添加数据包到音频包列表中
     void addAudioPkt(AVPacket &pkt);
     //清空音频包列表
     void clearAudioPktList();
     //SDL填充缓冲区的回调函数
     static void sdlAudioCallbackFunc(void *userdata, Uint8 *stream, int len);
     //SDL填充缓冲区的回调函数
     void sdlAudioCallback(Uint8 *stream, int len);
     //音频解码
     int decodeAudio();
     //初始化音频重采样
     int initSwr();
     void clearVideoPktList();
private:
     // 解封装上下文
     AVFormatContext * m_fmtCtx = nullptr;
     bool        m_fmtCtxCanFree = false;
     State m_TaskState;
     QString m_FileName;
     int     m_seekTime;
     double     m_speedPlayRate;
public:
     int initDecoder(AVCodecContext** decodeCtx,AVStream** stream,AVMediaType type);
     //初始化视频信息
     int initVideoInfo();
     //初始化视频像素格式转换
     int initSws();
     int decodeVideo();
     // 读取文件数据
     void readFile();
     void free();
     void freeAudio();
     void freeVideo();
     //添加数据包到视频包列表中
     void addVideoPkt(AVPacket &pkt);
};

#endif // VIDEOPLAYER_H
